<template>
  <div class="har-viewer">
    <div v-if="!harFile" class="no-file">
      <div class="no-file-icon">📄</div>
      <h3>请选择一个 HAR 文件</h3>
      <p>从左侧文件列表中选择一个文件进行查看</p>
    </div>
    
    <div v-else class="file-content">
      <!-- 文件基本信息 -->
      <div class="file-header">
        <div class="file-title">
          <h2>{{ harFile.name }}</h2>
          <div class="file-meta">
            <span class="file-size">{{ formatFileSize(harFile.size) }}</span>
            <span class="file-time">{{ formatTime(harFile.uploadTime.getTime()) }}</span>
          </div>
        </div>
        <div class="file-actions">
          <button @click="exportData" class="export-btn">导出数据</button>
        </div>
      </div>
      
      <!-- 性能概览 -->
      <div class="performance-overview">
        <h3>性能概览</h3>
        <div class="metrics-grid">
          <div class="metric-card">
            <div class="metric-value">{{ metrics.totalRequests }}</div>
            <div class="metric-label">总请求数</div>
          </div>
          <div class="metric-card">
            <div class="metric-value">{{ formatFileSize(metrics.totalSize) }}</div>
            <div class="metric-label">总大小</div>
          </div>
          <div class="metric-card">
            <div class="metric-value">{{ formatTime(metrics.totalTime) }}</div>
            <div class="metric-label">总时间</div>
          </div>
          <div class="metric-card">
            <div class="metric-value">{{ metrics.cacheHitRate.toFixed(1) }}%</div>
            <div class="metric-label">缓存命中率</div>
          </div>
        </div>
      </div>
      
      <!-- 详细指标 -->
      <div class="detailed-metrics">
        <h3>详细指标</h3>
        <div class="metrics-section">
          <div class="metrics-group">
            <h4>响应时间</h4>
            <div class="metric-row">
              <span>平均响应时间</span>
              <span>{{ formatTime(metrics.averageResponseTime) }}</span>
            </div>
            <div class="metric-row">
              <span>最大响应时间</span>
              <span>{{ formatTime(metrics.maxResponseTime) }}</span>
            </div>
            <div class="metric-row">
              <span>最小响应时间</span>
              <span>{{ formatTime(metrics.minResponseTime) }}</span>
            </div>
            <div class="metric-row">
              <span>95% 分位数</span>
              <span>{{ formatTime(metrics.p95ResponseTime) }}</span>
            </div>
          </div>
          
          <div class="metrics-group">
            <h4>网络时间</h4>
            <div class="metric-row">
              <span>平均 DNS 时间</span>
              <span>{{ formatTime(metrics.averageDnsTime) }}</span>
            </div>
            <div class="metric-row">
              <span>平均连接时间</span>
              <span>{{ formatTime(metrics.averageConnectTime) }}</span>
            </div>
            <div class="metric-row">
              <span>平均 SSL 时间</span>
              <span>{{ formatTime(metrics.averageSslTime) }}</span>
            </div>
            <div class="metric-row">
              <span>平均 TTFB</span>
              <span>{{ formatTime(metrics.averageTtfb) }}</span>
            </div>
          </div>
        </div>
      </div>
      
      <!-- 资源类型统计 -->
      <div class="resource-stats">
        <h3>资源类型统计</h3>
        <div class="resource-list">
          <div 
            v-for="(stats, type) in metrics.resourceTypeStats" 
            :key="type"
            class="resource-item"
          >
            <div class="resource-type">{{ getResourceTypeName(type) }}</div>
            <div class="resource-details">
              <div class="resource-count">{{ stats.count }} 个请求</div>
              <div class="resource-size">{{ formatFileSize(stats.totalSize) }}</div>
              <div class="resource-time">{{ formatTime(stats.averageTime) }} 平均</div>
            </div>
          </div>
        </div>
      </div>
      
      <!-- 请求列表 -->
      <div class="requests-section">
        <div class="section-header">
          <h3>请求列表</h3>
          <div class="filters">
            <select v-model="selectedResourceType" @change="filterRequests">
              <option value="">所有类型</option>
              <option 
                v-for="type in resourceTypes" 
                :key="type" 
                :value="type"
              >
                {{ getResourceTypeName(type) }}
              </option>
            </select>
            <select v-model="sortBy" @change="sortRequests">
              <option value="time">按时间排序</option>
              <option value="size">按大小排序</option>
              <option value="url">按 URL 排序</option>
            </select>
            <select v-model="pageSize" @change="changePageSize(pageSize)">
              <option 
                v-for="size in pageSizeOptions" 
                :key="size" 
                :value="size"
              >
                {{ size }}条/页
              </option>
            </select>
          </div>
        </div>
        
        <!-- 统计信息 -->
        <div class="requests-stats">
          <span class="total-count">共 {{ totalRequests }} 条请求</span>
          <span class="current-range">
            显示第 {{ (currentPage - 1) * pageSize + 1 }} - {{ Math.min(currentPage * pageSize, totalRequests) }} 条
          </span>
        </div>
        
        <div class="requests-list">
          <div 
            v-for="(entry, index) in filteredRequests" 
            :key="`${entry.url}-${index}`"
            class="request-item"
            @click="selectRequest(entry)"
          >
            <div class="request-info">
              <div class="request-url" :title="entry.url">{{ entry.url }}</div>
              <div class="request-details">
                <span class="request-method">{{ entry.method }}</span>
                <span class="request-status" :class="getStatusClass(entry.status)">
                  {{ entry.status }}
                </span>
                <span class="request-type">{{ getResourceTypeName(entry.resourceType) }}</span>
                <span class="request-domain">{{ getDomain(entry.url) }}</span>
              </div>
              <div class="request-timing" v-if="entry.timings">
                <span class="timing-item">DNS: {{ formatTime(entry.timings.dns || 0) }}</span>
                <span class="timing-item">连接: {{ formatTime(entry.timings.connect || 0) }}</span>
                <span class="timing-item">SSL: {{ formatTime(entry.timings.ssl || 0) }}</span>
                <span class="timing-item">等待: {{ formatTime(entry.timings.wait || 0) }}</span>
              </div>
            </div>
            <div class="request-metrics">
              <div class="metric-row">
                <span class="metric-label">响应时间</span>
                <span class="metric-value">{{ formatTime(entry.time) }}</span>
              </div>
              <div class="metric-row">
                <span class="metric-label">大小</span>
                <span class="metric-value">{{ formatFileSize(entry.size) }}</span>
              </div>
              <div class="metric-row">
                <span class="metric-label">缓存</span>
                <span class="metric-value cache-status" :class="getCacheStatusClass(entry.cacheStatus)">
                  {{ getCacheStatusText(entry.cacheStatus) }}
                </span>
              </div>
            </div>
          </div>
        </div>
        
        <!-- 分页控件 -->
        <div class="pagination" v-if="totalPages > 1">
          <div class="pagination-info">
            <span>第 {{ currentPage }} 页，共 {{ totalPages }} 页</span>
          </div>
          <div class="pagination-controls">
            <button 
              class="pagination-btn" 
              :disabled="currentPage <= 1"
              @click="goToPrevPage"
            >
              <span>‹</span>
            </button>
            
            <div class="page-numbers">
              <button 
                v-for="page in getVisiblePages()" 
                :key="page"
                class="page-number"
                :class="{ active: page === currentPage, ellipsis: page === '...' }"
                :disabled="page === '...'"
                @click="page !== '...' && goToPage(page as number)"
              >
                {{ page }}
              </button>
            </div>
            
            <button 
              class="pagination-btn" 
              :disabled="currentPage >= totalPages"
              @click="goToNextPage"
            >
              <span>›</span>
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import type { HarFile, ParsedEntry, ResourceType } from '../types/har';
import { calculateMetrics } from '../utils/compareHar';

// Props
interface Props {
  harFile?: HarFile | null;
}

const props = defineProps<Props>();

// Emits
const emit = defineEmits<{
  'request-selected': [entry: ParsedEntry];
}>();

// Reactive data
const selectedResourceType = ref<string>('');
const sortBy = ref<string>('time');
const selectedRequest = ref<ParsedEntry | null>(null);

// 分页相关状态
const currentPage = ref<number>(1);
const pageSize = ref<number>(30);
const pageSizeOptions = [10, 30, 50, 100];

// Computed
const metrics = computed(() => {
  if (!props.harFile?.parsedData) {
    return {
      totalRequests: 0,
      totalSize: 0,
      totalTime: 0,
      cacheHitRate: 0,
      averageResponseTime: 0,
      maxResponseTime: 0,
      minResponseTime: 0,
      p95ResponseTime: 0,
      averageDnsTime: 0,
      averageConnectTime: 0,
      averageSslTime: 0,
      averageTtfb: 0,
      resourceTypeStats: {} as Record<ResourceType, any>
    };
  }
  return calculateMetrics(props.harFile.parsedData);
});

const resourceTypes = computed(() => {
  return Object.keys(metrics.value.resourceTypeStats) as ResourceType[];
});

// 所有过滤后的请求（不分页）
const allFilteredRequests = computed(() => {
  if (!props.harFile?.parsedData) return [];
  
  let requests = [...props.harFile.parsedData];
  
  // 按资源类型筛选
  if (selectedResourceType.value) {
    requests = requests.filter(r => r.resourceType === selectedResourceType.value);
  }
  
  // 排序
  requests.sort((a, b) => {
    switch (sortBy.value) {
      case 'time':
        return b.time - a.time;
      case 'size':
        return b.size - a.size;
      case 'url':
        return a.url.localeCompare(b.url);
      default:
        return 0;
    }
  });
  
  return requests;
});

// 分页后的请求列表
const filteredRequests = computed(() => {
  const start = (currentPage.value - 1) * pageSize.value;
  const end = start + pageSize.value;
  return allFilteredRequests.value.slice(start, end);
});

// 总页数
const totalPages = computed(() => {
  return Math.ceil(allFilteredRequests.value.length / pageSize.value);
});

// 总条数
const totalRequests = computed(() => {
  return allFilteredRequests.value.length;
});

// Methods
function formatFileSize(bytes: number): string {
  if (bytes === 0) return '0 B';
  const k = 1024;
  const sizes = ['B', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}

function formatTime(ms: number): string {
  if (ms < 1000) return `${ms.toFixed(0)}ms`;
  return `${(ms / 1000).toFixed(2)}s`;
}

function getResourceTypeName(type: string): string {
  const typeNames: Record<string, string> = {
    'document': '文档',
    'stylesheet': '样式表',
    'image': '图片',
    'media': '媒体',
    'font': '字体',
    'script': '脚本',
    'xhr': 'XHR',
    'fetch': 'Fetch',
    'websocket': 'WebSocket',
    'manifest': '清单',
    'other': '其他'
  };
  return typeNames[type] || type;
}

function getStatusClass(status: number): string {
  if (status >= 200 && status < 300) return 'status-success';
  if (status >= 300 && status < 400) return 'status-redirect';
  if (status >= 400 && status < 500) return 'status-client-error';
  if (status >= 500) return 'status-server-error';
  return 'status-unknown';
}

function getCacheStatusClass(cacheStatus: string): string {
  switch (cacheStatus) {
    case 'hit':
      return 'cache-hit';
    case 'miss':
      return 'cache-miss';
    case 'partial':
      return 'cache-partial';
    default:
      return 'cache-unknown';
  }
}

function getCacheStatusText(cacheStatus: string): string {
  switch (cacheStatus) {
    case 'hit':
      return '命中';
    case 'miss':
      return '未命中';
    case 'partial':
      return '部分';
    default:
      return '未知';
  }
}

function selectRequest(entry: ParsedEntry) {
  selectedRequest.value = entry;
  emit('request-selected', entry);
}

function filterRequests() {
  // 重置到第一页
  currentPage.value = 1;
}

function sortRequests() {
  // 重置到第一页
  currentPage.value = 1;
}

// 分页相关方法
function goToPage(page: number) {
  if (page >= 1 && page <= totalPages.value) {
    currentPage.value = page;
  }
}

function goToPrevPage() {
  if (currentPage.value > 1) {
    currentPage.value--;
  }
}

function goToNextPage() {
  if (currentPage.value < totalPages.value) {
    currentPage.value++;
  }
}

function changePageSize(newSize: number) {
  pageSize.value = newSize;
  currentPage.value = 1; // 重置到第一页
}

// 获取域名
function getDomain(url: string): string {
  try {
    const urlObj = new URL(url);
    return urlObj.hostname;
  } catch {
    return url.split('/')[2] || url;
  }
}

// 获取可见的页码
function getVisiblePages(): (number | string)[] {
  const total = totalPages.value;
  const current = currentPage.value;
  const pages: (number | string)[] = [];
  
  if (total <= 7) {
    // 如果总页数少于等于7页，显示所有页码
    for (let i = 1; i <= total; i++) {
      pages.push(i);
    }
  } else {
    // 总是显示第一页
    pages.push(1);
    
    if (current <= 4) {
      // 当前页在前4页
      for (let i = 2; i <= 5; i++) {
        pages.push(i);
      }
      pages.push('...');
      pages.push(total);
    } else if (current >= total - 3) {
      // 当前页在后4页
      pages.push('...');
      for (let i = total - 4; i <= total; i++) {
        pages.push(i);
      }
    } else {
      // 当前页在中间
      pages.push('...');
      for (let i = current - 1; i <= current + 1; i++) {
        pages.push(i);
      }
      pages.push('...');
      pages.push(total);
    }
  }
  
  return pages;
}

function exportData() {
  if (!props.harFile) return;
  
  const data = {
    file: {
      name: props.harFile.name,
      size: props.harFile.size,
      uploadTime: props.harFile.uploadTime
    },
    metrics: metrics.value,
    requests: props.harFile.parsedData
  };
  
  const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `${props.harFile.name.replace('.har', '')}_analysis.json`;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(url);
}

// Watch for file changes
watch(() => props.harFile, () => {
  selectedResourceType.value = '';
  sortBy.value = 'time';
  selectedRequest.value = null;
  currentPage.value = 1;
});
</script>

<style scoped>
.har-viewer {
  height: 100%;
  overflow-y: auto;
  padding: 24px;
  background: var(--background);
}

.no-file {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 500px;
  color: var(--text-secondary);
  text-align: center;
}

.no-file-icon {
  font-size: 80px;
  margin-bottom: 24px;
  opacity: 0.6;
  animation: float 3s ease-in-out infinite;
}

@keyframes float {
  0%, 100% {
    transform: translateY(0px);
  }
  50% {
    transform: translateY(-10px);
  }
}

.no-file h3 {
  margin: 0 0 12px 0;
  font-size: 24px;
  font-weight: 600;
  color: var(--text-primary);
}

.no-file p {
  margin: 0;
  font-size: 16px;
  color: var(--text-secondary);
}

.file-content {
  display: flex;
  flex-direction: column;
  gap: 32px;
  animation: fadeIn 0.3s ease-out;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.file-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding: 32px;
  background: var(--surface);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  border: 1px solid var(--border);
  position: relative;
  overflow: hidden;
}

.file-header::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(135deg, var(--primary-color), #8b5cf6);
}

.file-title h2 {
  margin: 0 0 12px 0;
  color: var(--text-primary);
  font-size: 28px;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 12px;
}

.file-title h2::before {
  content: '📊';
  font-size: 24px;
}

.file-meta {
  display: flex;
  gap: 24px;
  font-size: 14px;
  color: var(--text-secondary);
  margin-top: 8px;
}

.file-meta span {
  background: var(--surface-hover);
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  font-weight: 500;
}

.export-btn {
  padding: 12px 24px;
  background: var(--primary-color);
  color: white;
  border: none;
  border-radius: var(--radius-md);
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  transition: var(--transition);
  box-shadow: var(--shadow-sm);
}

.export-btn:hover {
  background: var(--primary-hover);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.performance-overview {
  background: var(--surface);
  padding: 32px;
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  border: 1px solid var(--border);
}

.performance-overview h3 {
  margin: 0 0 24px 0;
  color: var(--text-primary);
  font-size: 20px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}

.performance-overview h3::before {
  content: '⚡';
  font-size: 18px;
}

.metrics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
}

.metric-card {
  text-align: center;
  padding: 24px;
  background: var(--surface-hover);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  transition: var(--transition);
  position: relative;
  overflow: hidden;
}

.metric-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(135deg, var(--primary-light), #f0f9ff);
  opacity: 0;
  transition: var(--transition);
}

.metric-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}

.metric-card:hover::before {
  opacity: 0.3;
}

.metric-value {
  font-size: 32px;
  font-weight: 700;
  color: var(--primary-color);
  margin-bottom: 8px;
  position: relative;
  z-index: 1;
}

.metric-label {
  font-size: 13px;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-weight: 600;
  position: relative;
  z-index: 1;
}

.detailed-metrics {
  background: var(--surface);
  padding: 32px;
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  border: 1px solid var(--border);
}

.detailed-metrics h3 {
  margin: 0 0 24px 0;
  color: var(--text-primary);
  font-size: 20px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}

.detailed-metrics h3::before {
  content: '📈';
  font-size: 18px;
}

.metrics-section {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
  gap: 32px;
}

.metrics-group {
  background: var(--surface-hover);
  padding: 24px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
}

.metrics-group h4 {
  margin: 0 0 20px 0;
  color: var(--text-primary);
  font-size: 18px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}

.metric-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 0;
  border-bottom: 1px solid var(--border-light);
  transition: var(--transition);
}

.metric-row:hover {
  background: var(--surface);
  margin: 0 -12px;
  padding: 12px;
  border-radius: var(--radius-sm);
}

.metric-row:last-child {
  border-bottom: none;
}

.metric-row span:first-child {
  color: var(--text-secondary);
  font-weight: 500;
}

.metric-row span:last-child {
  color: var(--text-primary);
  font-weight: 600;
  font-family: 'JetBrains Mono', monospace;
}

.resource-stats {
  background: var(--surface);
  padding: 32px;
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  border: 1px solid var(--border);
}

.resource-stats h3 {
  margin: 0 0 24px 0;
  color: var(--text-primary);
  font-size: 20px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}

.resource-stats h3::before {
  content: '📦';
  font-size: 18px;
}

.resource-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.resource-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  background: var(--surface-hover);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  transition: var(--transition);
}

.resource-item:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
  border-color: var(--primary-color);
}

.resource-type {
  font-weight: 600;
  color: var(--text-primary);
  font-size: 16px;
}

.resource-details {
  display: flex;
  gap: 20px;
  font-size: 14px;
  color: var(--text-secondary);
}

.resource-details span {
  background: var(--surface);
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  font-weight: 500;
  border: 1px solid var(--border);
}

.requests-section {
  background: var(--surface);
  padding: 32px;
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  border: 1px solid var(--border);
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
}

.section-header h3 {
  margin: 0;
  color: var(--text-primary);
  font-size: 20px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}

.section-header h3::before {
  content: '🔍';
  font-size: 18px;
}

.filters {
  display: flex;
  gap: 12px;
}

.filters select {
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-size: 14px;
  background: var(--surface);
  color: var(--text-primary);
  transition: var(--transition);
  min-width: 120px;
}

.filters select:focus {
  outline: none;
  border-color: var(--primary-color);
  box-shadow: 0 0 0 3px var(--primary-light);
}

.requests-stats {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: var(--surface-hover);
  border-radius: var(--radius-md);
  margin-bottom: 16px;
  font-size: 14px;
  color: var(--text-secondary);
  border: 1px solid var(--border);
}

.total-count {
  font-weight: 600;
  color: var(--text-primary);
}

.current-range {
  font-size: 13px;
}

.requests-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: 500px;
  overflow-y: auto;
  padding-right: 8px;
}

.request-item {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding: 20px;
  border: 2px solid var(--border);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: var(--transition);
  background: var(--surface);
  position: relative;
  overflow: hidden;
  margin-bottom: 8px;
  gap: 20px;
}

.request-item::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--primary-light);
  opacity: 0;
  transition: var(--transition);
}

.request-item:hover {
  border-color: var(--primary-color);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.request-item:hover::before {
  opacity: 0.1;
}

.request-info {
  flex: 1;
  min-width: 0;
  position: relative;
  z-index: 1;
}

.request-url {
  font-family: 'JetBrains Mono', 'Fira Code', monospace;
  font-size: 15px;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 12px;
  font-weight: 600;
  line-height: 1.4;
}

.request-details {
  display: flex;
  gap: 12px;
  font-size: 13px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}

.request-domain {
  color: var(--text-secondary);
  background: var(--surface-hover);
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  font-weight: 500;
  font-size: 12px;
  border: 1px solid var(--border);
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.request-timing {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 8px;
}

.timing-item {
  font-size: 11px;
  color: var(--text-muted);
  background: var(--surface-hover);
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  font-family: 'JetBrains Mono', monospace;
  border: 1px solid var(--border);
}

.request-method {
  font-weight: 700;
  color: var(--primary-color);
  background: var(--primary-light);
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  font-size: 12px;
  letter-spacing: 0.5px;
}

.request-status {
  font-weight: 700;
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  font-size: 12px;
  letter-spacing: 0.5px;
}

.status-success { 
  color: #166534;
  background: #dcfce7;
  border: 1px solid #bbf7d0;
}

.status-redirect { 
  color: #92400e;
  background: #fef3c7;
  border: 1px solid #fde68a;
}

.status-client-error, 
.status-server-error { 
  color: #991b1b;
  background: #fecaca;
  border: 1px solid #fca5a5;
}

.status-unknown { 
  color: var(--text-primary);
  background: var(--surface-hover);
  border: 1px solid var(--border);
}

.request-type {
  color: var(--text-primary);
  background: var(--surface-hover);
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  font-weight: 600;
  font-size: 12px;
  border: 1px solid var(--border);
}

.request-metrics {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  font-size: 13px;
  color: var(--text-primary);
  gap: 8px;
  position: relative;
  z-index: 1;
  min-width: 120px;
}

.metric-row {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}

.metric-label {
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-weight: 600;
}

.metric-value {
  background: var(--surface-hover);
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  font-weight: 700;
  font-family: 'JetBrains Mono', monospace;
  border: 1px solid var(--border);
  color: var(--text-primary);
  font-size: 12px;
  min-width: 60px;
  text-align: center;
}

.cache-status.cache-hit {
  color: #166534;
  background: #dcfce7;
  border-color: #bbf7d0;
}

.cache-status.cache-miss {
  color: #991b1b;
  background: #fecaca;
  border-color: #fca5a5;
}

.cache-status.cache-partial {
  color: #92400e;
  background: #fef3c7;
  border-color: #fde68a;
}

.cache-status.cache-unknown {
  color: var(--text-muted);
  background: var(--surface-hover);
  border-color: var(--border);
}

/* 分页控件样式 */
.pagination {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 24px;
  padding: 20px;
  background: var(--surface-hover);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
}

.pagination-info {
  font-size: 14px;
  color: var(--text-secondary);
  font-weight: 500;
}

.pagination-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pagination-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-primary);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: var(--transition);
  font-size: 16px;
  font-weight: 600;
}

.pagination-btn:hover:not(:disabled) {
  background: var(--primary-color);
  color: white;
  border-color: var(--primary-color);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}

.pagination-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: var(--surface-hover);
  color: var(--text-muted);
}

.page-numbers {
  display: flex;
  gap: 4px;
  margin: 0 12px;
}

.page-number {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 36px;
  padding: 0 8px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-primary);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: var(--transition);
  font-size: 14px;
  font-weight: 500;
}

.page-number:hover:not(:disabled) {
  background: var(--primary-light);
  border-color: var(--primary-color);
  color: var(--primary-color);
}

.page-number.active {
  background: var(--primary-color);
  color: white;
  border-color: var(--primary-color);
  font-weight: 700;
}

.page-number.ellipsis {
  cursor: default;
  background: transparent;
  border: none;
  color: var(--text-muted);
}

.page-number.ellipsis:hover {
  background: transparent;
  border: none;
  color: var(--text-muted);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .har-viewer {
    padding: 16px;
  }
  
  .file-header {
    flex-direction: column;
    gap: 16px;
    padding: 24px;
  }
  
  .file-title h2 {
    font-size: 24px;
  }
  
  .metrics-grid {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 16px;
  }
  
  .metric-card {
    padding: 20px;
  }
  
  .metric-value {
    font-size: 24px;
  }
  
  .metrics-section {
    grid-template-columns: 1fr;
    gap: 24px;
  }
  
  .section-header {
    flex-direction: column;
    gap: 16px;
    align-items: flex-start;
  }
  
  .filters {
    width: 100%;
    flex-wrap: wrap;
  }
  
  .filters select {
    flex: 1;
    min-width: 120px;
  }
  
  .resource-details {
    flex-direction: column;
    gap: 8px;
  }
  
  .request-details {
    flex-wrap: wrap;
    gap: 8px;
  }
  
  .request-item {
    flex-direction: column;
    gap: 16px;
  }
  
  .request-metrics {
    align-items: flex-start;
    width: 100%;
  }
  
  .metric-row {
    flex-direction: row;
    justify-content: space-between;
    width: 100%;
  }
  
  .pagination {
    flex-direction: column;
    gap: 16px;
    text-align: center;
  }
  
  .pagination-controls {
    justify-content: center;
  }
  
  .page-numbers {
    margin: 0 8px;
  }
  
  .page-number {
    min-width: 32px;
    height: 32px;
    font-size: 13px;
  }
  
  .pagination-btn {
    width: 32px;
    height: 32px;
    font-size: 14px;
  }
}

/* 滚动条样式 */
.requests-list::-webkit-scrollbar {
  width: 6px;
}

.requests-list::-webkit-scrollbar-track {
  background: var(--surface-hover);
  border-radius: 3px;
}

.requests-list::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 3px;
}

.requests-list::-webkit-scrollbar-thumb:hover {
  background: var(--text-muted);
}
</style>
